<template>
  <div class="adminer-container">
    <el-card v-loading="loading">
      <template #header>
        <div class="card-header">
          <span>用户管理</span>
          <el-radio-group
            v-model="activeTable"
            class="ml-auto"
            @change="handleTableChange"
          >
            <el-radio-button
              v-for="table in availableTables"
              :key="table.id"
              :label="table.name"
            >
              {{ table.description }}
            </el-radio-button>
          </el-radio-group>
        </div>
      </template>

      <!-- 动态查询表单 -->
      <el-form :inline="true" :model="queryForm" class="mb-4 mt-2">
        <div class="query-form-container">
          <!-- 始终显示的字段 -->
          <el-form-item
            v-for="field in defaultFields"
            :key="field.field_id"
            :label="field.label"
            class="!mb-2 query-form-item"
          >
            <template v-if="isEnumField(field.field)">
              <el-select
                v-model="queryForm[field.field]"
                :placeholder="'请选择' + field.label"
                clearable
                filterable
                class="!w-[180px]"
              >
                <el-option
                  v-for="option in getEnumOptions(field.field)"
                  :key="option"
                  :label="option"
                  :value="option"
                />
              </el-select>
            </template>
            <template v-else>
              <el-input
                v-model="queryForm[field.field]"
                :placeholder="'请输入' + field.label"
                clearable
                class="!w-[180px]"
              />
            </template>
          </el-form-item>
        </div>

        <!-- 可折叠的字段 -->
        <el-collapse-transition>
          <div v-show="!isCollapse" class="query-form-container mt-2">
            <el-form-item
              v-for="field in expandFields"
              :key="field.field_id"
              :label="field.label"
              class="!mb-2 query-form-item"
            >
              <template v-if="isEnumField(field.field)">
                <el-select
                  v-model="queryForm[field.field]"
                  :placeholder="'请选择' + field.label"
                  clearable
                  filterable
                  class="!w-[180px]"
                >
                  <el-option
                    v-for="option in getEnumOptions(field.field)"
                    :key="option"
                    :label="option"
                    :value="option"
                  />
                </el-select>
              </template>
              <template v-else>
                <el-input
                  v-model="queryForm[field.field]"
                  :placeholder="'请输入' + field.label"
                  clearable
                  class="!w-[180px]"
                />
              </template>
            </el-form-item>
          </div>
        </el-collapse-transition>

        <!-- 添加导入导出按钮 -->
        <el-form-item class="!ml-auto !mb-0 !mt-2">
          <div class="operation-buttons-container">
            <div class="operation-group">
              <el-tag
                type="warning"
                class="cursor-pointer operation-tag"
                @click="handleDownloadTemplate"
              >
                <el-icon class="mr-1"><Document /></el-icon>下载批量导入模板
              </el-tag>
              <el-upload
                v-if="hasImportPermission"
                class="upload-inline"
                :auto-upload="false"
                :show-file-list="false"
                accept=".xlsx,.xls"
                @change="file => handleImportExcel(file.raw)"
              >
                <el-tag type="primary" class="cursor-pointer operation-tag">
                  <el-icon class="mr-1"><Upload /></el-icon>导入人员数据Excel
                </el-tag>
              </el-upload>
              <el-tag
                v-if="hasExportPermission"
                type="success"
                class="cursor-pointer operation-tag"
                @click="handleExport"
              >
                <el-icon class="mr-1"><Download /></el-icon>导出人员数据Excel
              </el-tag>
            </div>
            <div class="operation-group">
              <el-upload
                v-if="hasUploadImagePermission"
                class="upload-inline"
                :auto-upload="false"
                :show-file-list="false"
                accept=".zip,.rar,.7z"
                :before-upload="handleBeforeUploadArchive"
                @change="file => handleUploadArchive(file.raw)"
              >
                <el-tag type="success" class="cursor-pointer operation-tag">
                  <el-icon class="mr-1"><FolderAdd /></el-icon
                  >上传证件照片压缩包
                </el-tag>
              </el-upload>
              <el-tag
                v-if="hasGenerateAuthCodePermission"
                type="info"
                class="cursor-pointer operation-tag"
                @click="handleGenerateAuthCode"
              >
                <el-icon class="mr-1"><Key /></el-icon>生成授权码
              </el-tag>
              <el-button type="primary" class="ml-8" @click="handleQuery">
                <el-icon class="mr-2 ml"><Search /></el-icon>查询
              </el-button>
              <el-button @click="resetForm">
                <el-icon class="mr-2"><Refresh /></el-icon>重置
              </el-button>
              <el-button @click="toggleCollapse">
                <el-icon v-if="isCollapse" class="mr-2">
                  <ArrowDown />
                </el-icon>
                <el-icon v-else class="mr-2">
                  <ArrowUp />
                </el-icon>
                {{ isCollapse ? "高级搜索" : "收起" }}
              </el-button>
              <el-button
                v-if="searchHistory.length > 0"
                type="info"
                @click="showSearchHistoryDialog"
              >
                <el-icon class="mr-2"><Clock /></el-icon>搜索历史
              </el-button>
            </div>
          </div>
        </el-form-item>
      </el-form>

      <!-- 用户列表 -->
      <PureTable
        row-key="id"
        :data="dataList"
        :columns="columns"
        :loading="loading"
        :pagination="isAuthCodeMode ? authCodePagination : pagination"
        border
        @page-size-change="onSizeChange"
        @page-current-change="onCurrentChange"
        @selection-change="handleSelectionChange"
      >
        <template #selection="{ row }">
          <el-checkbox
            v-model="row.selected"
            :disabled="row.have_id_number === '是'"
          />
        </template>
        <template
          v-for="col in photoColumns"
          :key="col.prop"
          #[col.prop]="{ row }"
        >
          <el-image
            :src="row[col.prop]"
            :preview-src-list="[row[col.prop]]"
            :initial-index="0"
            fit="cover"
            class="w-[40px] h-[40px] rounded-full cursor-pointer"
            preview-teleported
          />
        </template>
        <template #default="{ row, column }">
          <div
            :class="{
              'edited-cell': editedFields.get(row.id)?.has(column.property)
            }"
            @dblclick.stop="handleCellDblClick({ row, column })"
          >
            <template v-if="isEditing(row, column)">
              <template v-if="isEnumField(column.property)">
                <el-select
                  v-model="editingValue"
                  v-focus
                  size="small"
                  @change="handleEditConfirm(row, column)"
                  @blur="handleEditBlur"
                >
                  <el-option
                    v-for="option in getEnumOptions(column.property)"
                    :key="option"
                    :label="option"
                    :value="option"
                  />
                </el-select>
              </template>
              <template v-else>
                <el-input
                  v-model="editingValue"
                  v-focus
                  size="small"
                  @keyup.enter="handleEditConfirm(row, column)"
                  @blur="handleEditBlur"
                />
              </template>
            </template>
            <template v-else>
              <template v-if="isColumnVisible(column)">
                <span
                  v-if="
                    row[column.property] !== null &&
                    row[column.property] !== undefined &&
                    row[column.property] !== ''
                  "
                >
                  {{ row[column.property] }}
                </span>
                <span v-else class="text-gray-300">-</span>
              </template>
              <template v-else>
                <el-tag
                  type="info"
                  class="cursor-pointer"
                  @click="handleViewHiddenContent(row, column)"
                >
                  点击查看
                </el-tag>
              </template>
            </template>
          </div>
        </template>
        <template #operations="{ row }">
          <div class="flex items-center justify-center gap-3">
            <el-tag
              v-if="canEdit(row)"
              type="primary"
              effect="plain"
              class="cursor-pointer operation-tag !min-w-[64px]"
              @click="handleEdit(row)"
            >
              <el-icon class="mr-1"><Edit /></el-icon>编辑
            </el-tag>
            <el-tag
              v-if="hasDeletePermission"
              type="danger"
              effect="plain"
              class="cursor-pointer operation-tag !min-w-[64px]"
              @click="handleDelete(row)"
            >
              <el-icon class="mr-1"><Delete /></el-icon>删除
            </el-tag>
          </div>
        </template>
      </PureTable>

      <!-- 编辑对话框 -->
      <el-dialog
        v-model="dialogVisible"
        :title="dialogTitle"
        width="80%"
        destroy-on-close
        class="edit-dialog"
      >
        <el-scrollbar max-height="60vh">
          <el-form
            ref="formRef"
            :model="formData"
            :rules="formRules"
            label-width="100px"
            class="edit-form"
          >
            <div class="grid grid-cols-3 gap-2 mt-1">
              <el-form-item
                v-for="field in editableFields"
                :key="field.field_id"
                :label="field.label"
                :prop="field.field"
              >
                <template v-if="isEnumField(field.field)">
                  <el-select
                    v-model="formData[field.field]"
                    :placeholder="'请选择' + field.label"
                    :disabled="!hasFieldSetPermission(field.field)"
                    :class="{
                      'is-disabled': !hasFieldSetPermission(field.field)
                    }"
                  >
                    <el-option
                      v-for="option in getEnumOptions(field.field)"
                      :key="option"
                      :label="option"
                      :value="option"
                    />
                  </el-select>
                </template>
                <template v-else>
                  <el-input
                    v-model="formData[field.field]"
                    :placeholder="'请输入' + field.label"
                    :disabled="!hasFieldSetPermission(field.field)"
                    :class="{
                      'is-disabled': !hasFieldSetPermission(field.field)
                    }"
                  />
                </template>
              </el-form-item>
            </div>
          </el-form>
        </el-scrollbar>
        <template #footer>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSubmit">确定</el-button>
        </template>
      </el-dialog>

      <!-- 导出设置弹框 -->
      <el-dialog
        v-model="exportDialogVisible"
        :title="exportMode === 'export' ? '导出设置' : '模板设置'"
        width="800px"
        destroy-on-close
      >
        <el-form label-width="120px">
          <!-- 仅在导出模式下显示查询条件和导出数量 -->
          <template v-if="exportMode === 'export'">
            <el-form-item label="查询条件">
              <div class="flex items-center justify-between w-full mb-2">
                <el-button
                  link
                  type="primary"
                  class="ml-auto"
                  @click="toggleExportQueryCollapse"
                >
                  <el-icon class="mr-1">
                    <component
                      :is="isExportQueryCollapse ? 'ArrowDown' : 'ArrowUp'"
                    />
                  </el-icon>
                  {{ isExportQueryCollapse ? "展开" : "收起" }}
                </el-button>
              </div>
              <el-collapse-transition>
                <div v-show="!isExportQueryCollapse" class="query-conditions">
                  <div class="grid grid-cols-2 gap-4">
                    <div
                      v-for="field in exportFields"
                      :key="field.field_id"
                      class="flex items-center !mb-2"
                    >
                      <el-tooltip
                        :content="field.label"
                        placement="top"
                        :show-after="1000"
                      >
                        <div class="flex items-center w-full">
                          <div class="label-container w-[80px] mr-2">
                            <span class="truncate inline-block"
                              >{{ field.label }}：</span
                            >
                          </div>
                          <el-input
                            v-model="exportQueryForm[field.field]"
                            :placeholder="'请输入' + field.label"
                            clearable
                            class="flex-1 !max-w-[180px]"
                          />
                        </div>
                      </el-tooltip>
                    </div>
                  </div>
                  <div class="flex justify-start mt-4 gap-2">
                    <el-tag
                      type="primary"
                      class="cursor-pointer operation-tag"
                      @click="handleExportQuery"
                    >
                      <el-icon class="mr-1"><Search /></el-icon>查询
                    </el-tag>
                    <el-tag
                      class="cursor-pointer operation-tag"
                      @click="resetExportQuery"
                    >
                      <el-icon class="mr-1"><Refresh /></el-icon>重置
                    </el-tag>
                  </div>
                </div>
              </el-collapse-transition>
            </el-form-item>

            <el-form-item label="导出数据条数">
              <el-input-number
                v-model="exportFormData.count"
                :min="1"
                :max="1000"
                controls-position="right"
                class="!w-[180px]"
                :disabled="
                  !!exportFormData.startPage || !!exportFormData.endPage
                "
              />
              <span class="text-gray-400 ml-2">
                {{ getExportCountText }}
              </span>
            </el-form-item>

            <!-- 添加页码范围选择 -->
            <el-form-item label="页码范围">
              <div class="flex items-center gap-2">
                <el-input-number
                  v-model="exportFormData.startPage"
                  :min="1"
                  controls-position="right"
                  placeholder="起始页码"
                  class="!w-[180px]"
                  @change="handlePageRangeChange"
                />
                <span class="text-gray-400">至</span>
                <el-input-number
                  v-model="exportFormData.endPage"
                  :min="1"
                  controls-position="right"
                  placeholder="结束页码"
                  class="!w-[180px]"
                  @change="handlePageRangeChange"
                />
              </div>
              <div class="text-gray-400 mt-1 text-sm">
                不填写则不限制页码范围，填写后将自动计算导出条数
              </div>
            </el-form-item>
          </template>

          <el-form-item
            :label="exportMode === 'export' ? '选择导出字段' : '选择模板字段'"
          >
            <div class="field-selection">
              <div class="mb-2 flex items-center">
                <el-button type="primary" link @click="selectAllFields"
                  >全选</el-button
                >
                <el-button type="primary" link @click="unselectAllFields"
                  >取消全选</el-button
                >
                <span class="text-gray-400 ml-auto"
                  >已选择 {{ selectedFields.length }} 个字段</span
                >
              </div>
              <el-checkbox-group v-model="selectedFields" class="w-full">
                <div class="grid grid-cols-4 gap-4">
                  <el-checkbox
                    v-for="field in exportFields"
                    :key="field.field_id"
                    :label="field.field"
                    class="!flex items-center"
                  >
                    <el-tooltip
                      :content="field.label"
                      placement="top"
                      :show-after="1000"
                    >
                      <span class="truncate">{{ field.label }}</span>
                    </el-tooltip>
                  </el-checkbox>
                </div>
              </el-checkbox-group>
            </div>
          </el-form-item>
        </el-form>

        <!-- 预览表格 -->
        <div class="preview-table mt-4">
          <div class="text-gray-500 mb-2 font-bold">数据格式预览：</div>
          <el-table
            :data="previewData"
            border
            size="small"
            max-height="300"
            class="w-full"
          >
            <el-table-column
              v-for="field in selectedPreviewFields"
              :key="field.field_id"
              :prop="field.field"
              :label="field.label"
              align="center"
              show-overflow-tooltip
            />
          </el-table>
        </div>

        <template #footer>
          <div class="flex items-center justify-between w-full px-4">
            <span class="text-gray-400">提示：鼠标悬浮可以查看完整名称</span>
            <div>
              <el-button @click="exportDialogVisible = false">取消</el-button>
              <el-button type="primary" @click="confirmExport">
                {{ exportMode === "export" ? "确定导出" : "确定下载" }}
              </el-button>
            </div>
          </div>
        </template>
      </el-dialog>

      <!-- 授权码导出对话框 -->
      <el-dialog
        v-model="authCodeExportDialogVisible"
        :title="'导出授权码'"
        width="800px"
        destroy-on-close
      >
        <el-form label-width="120px">
          <el-form-item :label="'选择导出字段'">
            <div class="field-selection">
              <div class="mb-2 flex items-center">
                <el-button type="primary" link @click="selectAllAuthCodeFields"
                  >全选</el-button
                >
                <el-button
                  type="primary"
                  link
                  @click="unselectAllAuthCodeFields"
                  >取消全选</el-button
                >
                <span class="text-gray-400 ml-auto"
                  >已选择 {{ selectedAuthCodeFields.length }} 个字段</span
                >
              </div>
              <el-checkbox-group
                v-model="selectedAuthCodeFields"
                class="w-full"
              >
                <div class="grid grid-cols-4 gap-4">
                  <el-checkbox
                    v-for="field in authCodeExportFields"
                    :key="field.field_id"
                    :label="field.field"
                    class="!flex items-center"
                  >
                    <el-tooltip
                      :content="field.label"
                      placement="top"
                      :show-after="1000"
                    >
                      <span class="truncate">{{ field.label }}</span>
                    </el-tooltip>
                  </el-checkbox>
                </div>
              </el-checkbox-group>
            </div>
          </el-form-item>
        </el-form>

        <!-- 预览表格 -->
        <div class="preview-table mt-4">
          <div class="text-gray-500 mb-2 font-bold">数据格式预览：</div>
          <el-table
            :data="authCodePreviewData"
            border
            size="small"
            max-height="300"
            class="w-full"
          >
            <el-table-column
              v-for="field in previewFields"
              :key="field.field_id"
              :prop="field.field"
              :label="field.label"
              align="center"
              show-overflow-tooltip
            />
          </el-table>
        </div>

        <template #footer>
          <div class="flex items-center justify-between w-full px-4">
            <span class="text-gray-400">提示：鼠标悬浮可以查看完整名称</span>
            <div>
              <el-button @click="authCodeExportDialogVisible = false"
                >取消</el-button
              >
              <el-button type="primary" @click="handleAuthCodeExport">
                确定导出
              </el-button>
            </div>
          </div>
        </template>
      </el-dialog>

      <!-- 搜索历史弹出框 -->
      <el-dialog
        v-model="searchHistoryDialogVisible"
        title="搜索历史"
        width="600px"
        destroy-on-close
      >
        <div class="search-history-dialog">
          <div v-if="searchHistory.length > 0" class="search-history-list">
            <div
              v-for="(history, index) in searchHistory"
              :key="index"
              class="search-history-item"
              style="cursor: pointer"
              @click="applySearchHistory(history)"
            >
              <div class="search-history-content">
                <div class="search-history-label">
                  {{ getHistoryLabel(history) }}
                </div>
                <div class="search-history-time">
                  {{ formatTime(history.timestamp) }}
                </div>
              </div>
              <div class="search-history-actions">
                <el-button
                  type="danger"
                  link
                  @click.stop="removeSearchHistory(index)"
                >
                  删除
                </el-button>
              </div>
            </div>
          </div>
          <div v-else class="search-history-empty">暂无搜索历史</div>
        </div>
        <template #footer>
          <div class="dialog-footer">
            <el-button @click="searchHistoryDialogVisible = false"
              >关闭</el-button
            >
            <el-button type="danger" @click="clearSearchHistory"
              >清空历史</el-button
            >
          </div>
        </template>
      </el-dialog>
    </el-card>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, computed, nextTick, h } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import {
  Search,
  Refresh,
  ArrowDown,
  ArrowUp,
  Edit,
  Download,
  Upload,
  Document,
  Key,
  FolderAdd,
  Delete,
  Clock
} from "@element-plus/icons-vue";
import {
  getMyUser,
  baseUrlApi,
  getAllTableField,
  getMyPermissions,
  setTableRecord,
  getMyTable,
  getTableRecords,
  exportUser,
  importField,
  generateCertificateNumber,
  uploadFile,
  deleteTableRecord
} from "@/api/index";
import PureTable from "@pureadmin/table";
import type { FormInstance } from "element-plus";
import ExcelJS from "exceljs";

// 添加配置接口定义
interface FieldConfig {
  width?: number;
  align?: "left" | "center" | "right";
  [key: string]: any;
}

// 修改列配置的类型定义
interface TableColumn {
  label?: string;
  prop?: string;
  minWidth?: number;
  width?: number;
  align?: "left" | "center" | "right" | string;
  slot?: string;
  fixed?: boolean | "left" | "right";
  sortable?: boolean;
  className?: string;
  type?: "selection" | "index";
}

// 修改字段定义接口
interface Field {
  field_id: number;
  table_id?: number;
  field: string;
  type: string;
  view_permission?: number;
  set_permission?: number;
  created_at?: string;
  updated_at?: string;
  config?: string;
  label: string;
  must?: string;
}

// 添加表格接口定义
interface TableInfo {
  id: number;
  name: string;
  description: string;
}

// 添加表格切换相关的状态
const activeTable = ref("");
const availableTables = ref<TableInfo[]>([]);

// 获取用户可访问的表
const fetchAvailableTables = async () => {
  try {
    const res = await getMyTable();
    if (res.status === "success") {
      // 使用 Map 来去重，以 id 为键
      const uniqueTables = new Map();
      res.data.forEach(table => {
        uniqueTables.set(table.id, table);
      });
      // 将 Map 转换回数组
      availableTables.value = Array.from(uniqueTables.values());
      // 默认选中第一个表
      if (availableTables.value.length > 0) {
        activeTable.value = availableTables.value[0].name;
      }
    }
  } catch (error) {
    console.error("获取表信息失败:", error);
    ElMessage.error("获取表信息失败");
  }
};

// 定义tableId和tableField为计算属性
const tableId = computed(() => {
  const currentTable = availableTables.value.find(
    t => t.name === activeTable.value
  );
  return currentTable?.id || 0;
});

const tableField = computed(() => activeTable.value);

const loading = ref(false);
const dataList = ref([]);
const fields = ref<Field[]>([]);
const columns = ref([]);

// 分页配置
const pagination = reactive({
  pageSize: 10,
  currentPage: 1,
  pageSizes: [10, 15, 20],
  total: 0,
  align: "right",
  background: true,
  size: "default"
});

// 查询表单数据 - 动态生成
const queryForm = reactive({});

// 折叠状态
const isCollapse = ref(true);
// 默认显示的字段数量
const DEFAULT_SHOW_FIELDS = 4;

// 计算默认显示的字段（前4个）
const defaultFields = computed(() => {
  return fields.value.slice(0, DEFAULT_SHOW_FIELDS);
});

// 计算展开显示的字段（第5个开始）
const expandFields = computed(() => {
  return fields.value.slice(DEFAULT_SHOW_FIELDS);
});

// 切换折叠状态
const toggleCollapse = () => {
  isCollapse.value = !isCollapse.value;
};

// 编辑相关的响应式变量
const dialogVisible = ref(false);
const dialogTitle = ref("");
const formRef = ref<FormInstance>();
const formData = reactive({});
const formRules = reactive({});
const currentRow = ref(null);

// 可编辑字段（排除某些不可编辑的字段）
const editableFields = computed(() => {
  return fields.value.filter(
    field => !["id", "created_at", "updated_at"].includes(field.field)
  );
});

// 添加编辑相关的状态
const editingCell = ref<{ rowId: string | number | null; prop: string | null }>(
  {
    rowId: null,
    prop: null
  }
);
const editingValue = ref("");

// 添加一个标记，用于防止重复触发
const isConfirming = ref(false);

// 自定义指令：自动聚焦
const vFocus = {
  mounted: el => {
    const input = el.querySelector("input");
    if (input) {
      input.focus();
      input.select();
    }
  }
};

// 判断单元格是否处于编辑状态
const isEditing = (row: any, column: any) => {
  return (
    editingCell.value.rowId === row.id &&
    editingCell.value.prop === column.property &&
    column.property !== "photo" && // 排除不可编辑的列
    !["id", "created_at", "updated_at"].includes(column.property)
  );
};

// 处理单元格双击事件
const handleCellDblClick = ({ row, column }) => {
  if (
    column.property &&
    column.property !== "photo" &&
    !["id", "created_at", "updated_at"].includes(column.property) &&
    hasFieldSetPermission(column.property) // 添加权限检查
  ) {
    editingCell.value = {
      rowId: row.id,
      prop: column.property
    };
    editingValue.value = row[column.property] ?? ""; // 使用空值合并运算符，支持空值编辑
  }
};

// 处理编辑确认
const handleEditConfirm = async (row: any, column: any) => {
  // 如果没有正在编辑，或者正在确认中，则直接返回
  if (
    !editingCell.value.rowId ||
    !editingCell.value.prop ||
    isConfirming.value
  ) {
    return;
  }

  try {
    isConfirming.value = true; // 设置确认中标记

    // 获取原始值和新值
    const originalValue = row[column.property];
    const newValue = editingValue.value.trim();

    // 如果值没有变化，直接取消编辑
    if (originalValue === newValue) {
      cancelEdit();
      return;
    }

    // 构建变化信息
    const fieldLabel =
      fields.value.find(f => f.field === column.property)?.label ||
      column.property;
    const changeMessage = `
      <div class="change-message">
        <div class="change-header">
          <span class="user-name">姓名：${row.name}</span>
        </div>
        <div class="change-content">
          <div class="field-name">${fieldLabel}:</div>
          <div class="value-change">
            <span class="old-value">原数据: ${originalValue || "-"}</span>
            <span class="arrow">→</span>
            <span class="new-value">新数据: ${newValue || "-"}</span>
          </div>
        </div>
      </div>
    `;

    const confirmResult = await ElMessageBox.confirm(
      `<div class="confirm-change">
        <div class="change-title">确认修改以下数据？</div>
        ${changeMessage}
      </div>`,
      "提示",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        dangerouslyUseHTMLString: true,
        customClass: "edit-confirm-dialog",
        beforeClose: (action, instance, done) => {
          if (action === "cancel") {
            cancelEdit();
          }
          done();
        }
      }
    ).catch(() => {
      cancelEdit();
      return false;
    });

    if (!confirmResult) {
      return;
    }

    // 获取字段类型
    const fieldType = fields.value.find(f => f.field === column.property)?.type;

    // 根据字段类型处理值
    let processedValue: string | number = newValue;
    if (fieldType === "int" && processedValue !== "") {
      processedValue = parseInt(processedValue as string);
    }

    // 构建请求数据
    const requestData = {
      table_id: tableId.value,
      record_id: row.id,
      [column.property]: processedValue || null
    };

    // 调用setTableRecord接口更新数据
    const res = await setTableRecord(requestData);

    if (res.status === "success") {
      // 更新本地数据
      row[column.property] = processedValue || null;

      // 记录编辑过的字段
      if (!editedFields.value.has(row.id)) {
        editedFields.value.set(row.id, new Set());
      }
      editedFields.value.get(row.id)?.add(column.property);

      // 显示成功消息，包含变化信息
      ElMessage({
        message: h("div", {
          innerHTML: `
            <div class="success-message">
              <div>更新成功</div>
              ${changeMessage}
            </div>
          `,
          class: "edit-success-message"
        }),
        type: "success",
        duration: 1000,
        dangerouslyUseHTMLString: true,
        customClass: "edit-success-notification"
      });

      cancelEdit();
    } else {
      ElMessage.error(res.message || "更新失败");
    }
  } catch (error) {
    console.error("更新失败:", error);
    ElMessage.error("更新失败");
  } finally {
    isConfirming.value = false; // 重置确认中标记
  }
};

// 处理编辑失焦
const handleEditBlur = () => {
  // 如果正在编辑状态且不在确认中，则取消编辑
  if (
    editingCell.value.rowId &&
    editingCell.value.prop &&
    !isConfirming.value
  ) {
    cancelEdit();
  }
};

// 取消编辑
const cancelEdit = () => {
  editingCell.value = {
    rowId: null,
    prop: null
  };
  editingValue.value = "";
  isConfirming.value = false; // 重置确认中标记
};

// 添加权限相关的响应式变量
const permissions = ref<string[]>([]);

// 获取用户权限
const fetchPermissions = async () => {
  try {
    const res = await getMyPermissions();
    if (res.status === "success") {
      // 提取所有权限名称
      permissions.value = res.data.map(item => item.name);
    }
  } catch (error) {
    console.error("获取权限失败:", error);
    ElMessage.error("获取权限失败");
  }
};

// 检查字段是否有修改权限
const hasFieldSetPermission = (field: string) => {
  return permissions.value.includes(`table.${tableField.value}.${field}.set`);
};

// 移除硬编码的fieldLabelMap
const fieldLabelMap = ref<Record<string, string>>({});

// 添加操作列宽度的计算属性
const operationColumnWidth = computed(() => {
  // 检查是否有任何字段的修改权限
  const hasEditPermission = fields.value.some(
    field =>
      !["id", "created_at", "updated_at"].includes(field.field) &&
      hasFieldSetPermission(field.field)
  );
  // 如果同时有编辑和删除权限，返回180，否则返回100
  return hasDeletePermission.value && hasEditPermission ? 180 : 100;
});

// 修改initColumns方法
const initColumns = () => {
  // 添加选择列
  const selectionColumn: TableColumn = {
    type: "selection",
    width: 55,
    align: "center",
    fixed: "left"
  };

  const baseColumns = fields.value.map(field => {
    let config: FieldConfig = {};
    try {
      const parsedConfig = JSON.parse(field.config || "{}");
      config = {
        width:
          typeof parsedConfig.width === "number" ? parsedConfig.width : 120,
        align: ["left", "center", "right"].includes(parsedConfig.align)
          ? parsedConfig.align
          : "center",
        ...parsedConfig
      };
    } catch (e) {
      config = { width: 120, align: "center" };
    }

    const hasSetPermission = hasFieldSetPermission(field.field);

    const column: TableColumn = {
      label: field.label,
      prop: field.field,
      minWidth: config.width,
      align: config.align,
      slot: field.field.endsWith("_photo") ? field.field : "default",
      fixed:
        field.field === "id" || field.field === "name" ? "left" : undefined,
      className: !hasSetPermission ? "disabled-column" : ""
    };

    return column;
  });

  // 添加操作列
  baseColumns.unshift(selectionColumn);
  baseColumns.push({
    label: "操作",
    slot: "operations",
    fixed: "right",
    width: operationColumnWidth.value,
    align: "center"
  });

  columns.value = baseColumns;
};

// 双击行处理
const handleRowDblClick = row => {
  handleEdit(row);
};

// 编辑处理
const handleEdit = row => {
  currentRow.value = row;
  dialogTitle.value = "编辑用户(为空则不修改)";
  // 复制数据到表单
  Object.keys(row).forEach(key => {
    formData[key] = row[key];
  });
  dialogVisible.value = true;
};

// 删除处理
const handleDelete = async row => {
  try {
    await ElMessageBox.confirm(
      `确定要删除用户 "${row.name}" 吗？此操作不可恢复！`,
      "警告",
      {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning"
      }
    );

    const res = await deleteTableRecord({
      table_id: tableId.value,
      record_id: row.id
    });

    if (res.status === "success") {
      ElMessage.success("删除成功");
      fetchData(); // 刷新数据
    } else {
      ElMessage.error(res.message || "删除失败");
    }
  } catch (error) {
    if (error !== "cancel") {
      console.error("删除失败:", error);
      ElMessage.error("删除失败");
    }
  }
};

// 提交表单
const handleSubmit = async () => {
  if (!formRef.value) return;

  try {
    await formRef.value.validate();

    // 构建变化信息
    const changes = [];
    const changedData = {};

    // 检查每个字段的变化
    Object.keys(formData).forEach(key => {
      // 跳过id等不可编辑字段
      if (["id", "created_at", "updated_at"].includes(key)) return;

      const originalValue = currentRow.value[key];
      const newValue = formData[key];

      // 如果值发生变化，记录下来
      if (originalValue !== newValue) {
        const fieldLabel =
          fields.value.find(f => f.field === key)?.label || key;
        changes.push(`
          <div class="change-message">
            <div class="change-header">
              <span class="user-name">姓名：${currentRow.value.name}</span>
            </div>
            <div class="change-content">
              <div class="field-name">${fieldLabel}:</div>
              <div class="value-change">
                <span class="old-value">原数据: ${originalValue || "-"}</span>
                <span class="arrow">→</span>
                <span class="new-value">新数据: ${newValue || "-"}</span>
              </div>
            </div>
          </div>
        `);
        changedData[key] = newValue;
      }
    });

    // 如果没有任何变化，直接关闭对话框
    if (changes.length === 0) {
      ElMessage.info("数据没有发生变化");
      dialogVisible.value = false;
      return;
    }

    // 构建确认消息
    const confirmMessage = `
      <div class="confirm-change">
        <div class="change-title">确认修改以下数据？</div>
        ${changes.join("")}
      </div>
    `;

    // 显示确认对话框
    const confirmResult = await ElMessageBox.confirm(confirmMessage, "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning",
      dangerouslyUseHTMLString: true,
      customClass: "edit-confirm-dialog"
    }).catch(() => false);

    if (!confirmResult) return;

    // 调用setTableRecord接口更新数据
    const res = await setTableRecord({
      table_id: tableId.value,
      record_id: currentRow.value.id,
      ...changedData
    });

    if (res.status === "success") {
      // 记录编辑过的字段
      if (!editedFields.value.has(currentRow.value.id)) {
        editedFields.value.set(currentRow.value.id, new Set());
      }
      Object.keys(changedData).forEach(field => {
        editedFields.value.get(currentRow.value.id)?.add(field);
      });

      // 更新本地数据
      Object.keys(changedData).forEach(key => {
        const index = dataList.value.findIndex(
          item => item.id === currentRow.value.id
        );
        if (index !== -1) {
          dataList.value[index][key] = changedData[key];
        }
      });

      // 显示成功消息，包含变化信息
      ElMessage({
        message: h("div", {
          innerHTML: `
            <div class="success-message">
              <div>更新成功</div>
              ${changes.join("")}
            </div>
          `,
          class: "edit-success-message"
        }),
        type: "success",
        duration: 3000,
        dangerouslyUseHTMLString: true,
        customClass: "edit-success-notification"
      });

      dialogVisible.value = false;
    } else {
      ElMessage.error(res.message || "更新失败");
    }
  } catch (error) {
    console.error("更新失败:", error);
    ElMessage.error("更新失败");
  }
};

// 获取数据并设置表格列
const fetchData = async () => {
  loading.value = true;
  try {
    // 处理查询参数，过滤掉空值并确保汉字不被编码
    const queryParams = {};
    Object.keys(queryForm).forEach(key => {
      if (
        queryForm[key] !== "" &&
        queryForm[key] !== null &&
        queryForm[key] !== undefined
      ) {
        queryParams[key] = queryForm[key];
      }
    });

    const params = {
      page: pagination.currentPage,
      size: pagination.pageSize,
      table_id: tableId.value,
      ...queryParams
    };

    const res = await getMyUser(params);
    if (res.status === "success") {
      fields.value = res.data.field;
      // 构建字段映射
      fieldLabelMap.value = fields.value.reduce(
        (acc, field) => {
          acc[field.field] = field.label;
          return acc;
        },
        {} as Record<string, string>
      );

      initColumns();
      dataList.value = res.data.data.records;
      pagination.total = res.data.data.pagination.total;
      // 清空编辑记录
      editedFields.value.clear();
    }
  } catch (error) {
    console.error("获取数据失败:", error);
    ElMessage.error("获取数据失败");
  } finally {
    loading.value = false;
  }
};

// 重置表单
const resetForm = () => {
  Object.keys(queryForm).forEach(key => {
    queryForm[key] = "";
  });
  pagination.currentPage = 1;
  fetchData();
};

// 查询方法
const handleQuery = () => {
  pagination.currentPage = 1;

  // 添加到搜索历史
  const validQuery = Object.entries(queryForm).reduce((acc, [key, value]) => {
    if (value !== "" && value !== null && value !== undefined) {
      acc[key] = value;
    }
    return acc;
  }, {});

  // 如果有有效的查询条件，添加到历史记录
  if (Object.keys(validQuery).length > 0) {
    // 添加时间戳
    const historyItem = {
      ...validQuery,
      timestamp: Date.now()
    };

    // 检查是否已存在相同的查询条件
    const existingIndex = searchHistory.value.findIndex(history =>
      Object.entries(validQuery).every(([key, value]) =>
        key === "timestamp" ? true : history[key] === value
      )
    );

    if (existingIndex !== -1) {
      // 如果存在，将其移到最前面并更新时间戳
      searchHistory.value.splice(existingIndex, 1);
    }

    // 添加新的查询条件到历史记录
    searchHistory.value.unshift(historyItem);
    // 限制历史记录数量
    if (searchHistory.value.length > MAX_HISTORY_LENGTH) {
      searchHistory.value.pop();
    }

    // 保存到localStorage
    saveSearchHistory();
  }

  fetchData();
};

const onSizeChange = async (val: number) => {
  if (isAuthCodeMode.value) {
    authCodePagination.pageSize = val;
    await handleGenerateAuthCode();
  } else {
    pagination.pageSize = val;
    await fetchData();
  }
};

const onCurrentChange = async (val: number) => {
  if (isAuthCodeMode.value) {
    authCodePagination.currentPage = val;
    await handleGenerateAuthCode();
  } else {
    pagination.currentPage = val;
    await fetchData();
  }
};

// 修改导出相关的响应式变量
const exportDialogVisible = ref(false);
const exportFields = ref<Field[]>([]);
const selectedFields = ref<string[]>([]);
const exportFormData = reactive({
  count: 100,
  fields: [] as string[],
  startPage: null as number | null,
  endPage: null as number | null
});

// 添加导出模式
const exportMode = ref<"export" | "template">("export");

// 修改handleExport方法
const handleExport = async () => {
  try {
    // 获取字段信息
    const res = await getAllTableField({ table_id: tableId.value });
    if (res.status === "success") {
      exportFields.value = res.data;
      selectedFields.value = exportFields.value.map(field => field.field);
      exportMode.value = "export";

      // 自动获取第一页数据用于预览
      const previewRes = await exportUser({
        table_id: tableId.value,
        page: 1,
        size: 1
      });

      if (previewRes.status === "success") {
        exportQueryResult.value = previewRes.data.data.records;
      }

      exportDialogVisible.value = true;
    }
  } catch (error) {
    console.error("获取字段失败:", error);
    ElMessage.error("获取字段失败");
  }
};

// 修改handleDownloadTemplate方法
const handleDownloadTemplate = async () => {
  try {
    const res = await getAllTableField({ table_id: tableId.value });
    if (res.status === "success") {
      // 过滤掉ID字段和must为"排除"的字段
      const validFields = res.data.filter(
        field => field.field !== "id" && field.must !== "排除"
      );

      // 创建工作簿和工作表
      const workbook = new ExcelJS.Workbook();
      const worksheet = workbook.addWorksheet("用户数据模板");

      // 设置表头
      const headers = validFields.map(field => {
        // 如果字段是必填的，添加星号标记
        return field.must === "必须" ? `${field.label}*` : field.label;
      });
      worksheet.addRow(headers);

      // 设置表头样式
      const headerRow = worksheet.getRow(1);
      headerRow.font = { bold: true };
      headerRow.alignment = { vertical: "middle", horizontal: "center" };

      // 设置所有行的高度为统一值
      for (let i = 1; i <= 1000; i++) {
        const row = worksheet.getRow(i);
        row.height = 20; // 统一设置所有行高为20
      }

      // 设置列宽和样式
      headers.forEach((header, index) => {
        const column = worksheet.getColumn(index + 1);
        column.width = Math.max(15, header.length * 2);

        // 获取当前字段的配置
        const field = validFields[index];

        // 默认将所有单元格设置为文本格式
        column.numFmt = "@";

        // 为所有单元格设置文本格式（除了特殊计算字段）
        for (let i = 2; i <= 1000; i++) {
          const cell = worksheet.getCell(`${column.letter}${i}`);
          // 设置单元格格式为文本
          cell.numFmt = "@";
          // 不再添加前导单引号和默认值，让单元格保持空白状态
          cell.value = null;
        }

        // 为必填列添加背景色和边框
        if (field.must === "必须") {
          // 添加一个隐藏的验证工作表
          if (!workbook.getWorksheet("Validation")) {
            workbook.addWorksheet("Validation");
          }
          const validationSheet = workbook.getWorksheet("Validation");
          validationSheet.state = "hidden";

          // 为必填列添加背景色和边框
          for (let i = 2; i <= 1000; i++) {
            const cell = worksheet.getCell(`${column.letter}${i}`);
            // 设置背景色
            cell.fill = {
              type: "pattern",
              pattern: "solid",
              fgColor: { argb: "FFFFE0" } // 浅黄色背景
            };
            // 设置边框
            cell.border = {
              top: { style: "thin", color: { argb: "FFD3D3D3" } },
              left: { style: "thin", color: { argb: "FFD3D3D3" } },
              bottom: { style: "thin", color: { argb: "FFD3D3D3" } },
              right: { style: "thin", color: { argb: "FFD3D3D3" } }
            };
          }
        }

        // 如果是枚举类型字段，添加下拉选择
        if (field.type.startsWith("enum(")) {
          try {
            // 修改枚举值的解析方式
            const enumStr = field.type.substring(5, field.type.length - 1);
            const options = enumStr.split(",").map(
              option => option.replace(/['"]/g, "").trim() // 移除引号并清理空格
            );

            // 在主工作表中直接添加数据验证
            for (let i = 2; i <= 1000; i++) {
              const cell = worksheet.getCell(`${column.letter}${i}`);
              cell.dataValidation = {
                type: "list",
                allowBlank: field.must !== "必须",
                formulae: ['"' + options.join(",") + '"'], // 直接使用字符串列表
                showErrorMessage: true,
                errorStyle: "error",
                errorTitle: "错误",
                error: `请从下拉列表中选择有效的${field.label}`,
                prompt: `请选择${field.label}`
              };
            }
          } catch (e) {
            console.error("解析枚举值失败:", e);
          }
        }
      });

      // 冻结表头
      worksheet.views = [
        {
          state: "frozen",
          xSplit: 0,
          ySplit: 1,
          topLeftCell: "A2",
          activeCell: "A2"
        }
      ];

      // 隐藏验证工作表
      const validationSheet = workbook.getWorksheet("Validation");
      if (validationSheet) {
        validationSheet.state = "hidden";
      }

      // 生成二进制数据
      const buffer = await workbook.xlsx.writeBuffer();

      // 创建Blob对象
      const blob = new Blob([buffer], {
        type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
      });

      // 创建下载链接并触发下载
      const link = document.createElement("a");
      link.href = window.URL.createObjectURL(blob);
      // 获取当前表的描述作为文件名的一部分
      const currentTable = availableTables.value.find(
        t => t.name === activeTable.value
      );
      const tableName = currentTable?.description || "用户数据";
      link.download = `${tableName}导入模板.xlsx`;
      link.click();

      ElMessage.success("模板下载成功");
    }
  } catch (error) {
    console.error("获取字段失败:", error);
    ElMessage.error("下载模板失败");
  }
};

// 修改confirmExport方法
const confirmExport = async () => {
  if (exportMode.value === "export") {
    await handleExportConfirm();
  } else {
    await handleTemplateConfirm();
  }
};

// 拆分导出确认逻辑
const handleExportConfirm = async () => {
  try {
    if (selectedFields.value.length === 0) {
      ElMessage.warning("请至少选择一个导出字段");
      return;
    }

    // 检查导出数据量
    if (exportFormData.count > 1000) {
      ElMessage.warning("导出数据不能超过1000条");
      return;
    }

    // 检查页码范围
    if (
      exportFormData.startPage &&
      exportFormData.endPage &&
      exportFormData.startPage > exportFormData.endPage
    ) {
      ElMessage.warning("起始页码不能大于结束页码");
      return;
    }

    // 获取选中的字段信息
    const selectedFieldsInfo = exportFields.value.filter(field =>
      selectedFields.value.includes(field.field)
    );

    // 创建工作簿和工作表
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet("用户数据");

    // 设置表头
    const headers = selectedFieldsInfo.map(field => field.label);
    worksheet.addRow(headers);

    // 构建查询参数
    const params = {
      ...exportQueryForm,
      table_id: tableId.value
    };

    let exportData = [];

    // 根据页码范围获取数据
    if (exportFormData.startPage && exportFormData.endPage) {
      const totalPages = Math.ceil(pagination.total / pagination.pageSize);
      const validStartPage = Math.min(exportFormData.startPage, totalPages);
      const validEndPage = Math.min(exportFormData.endPage, totalPages);

      for (let page = validStartPage; page <= validEndPage; page++) {
        const pageParams = {
          ...params,
          page: page,
          size: pagination.pageSize
        };

        const res = await exportUser(pageParams);
        if (res.status !== "success") {
          throw new Error(res.message || "获取数据失败");
        }

        exportData = exportData.concat(res.data.data.records);

        // 如果数据量超过1000条，则停止获取
        if (exportData.length >= 1000) {
          exportData = exportData.slice(0, 1000);
          break;
        }
      }
    } else {
      // 不指定页码范围时，直接获取指定数量的数据
      const res = await exportUser({
        ...params,
        page: 1,
        size: Math.min(exportFormData.count, 1000)
      });
      if (res.status !== "success") {
        throw new Error(res.message || "获取数据失败");
      }
      exportData = res.data.data.records;
    }

    // 添加数据
    exportData.forEach(item => {
      const rowData = selectedFieldsInfo.map(field => item[field.field] || "");
      worksheet.addRow(rowData);
    });

    // 设置表头样式
    const headerRow = worksheet.getRow(1);
    headerRow.font = { bold: true };
    headerRow.alignment = { vertical: "middle", horizontal: "center" };

    // 设置列宽
    headers.forEach((header, index) => {
      const column = worksheet.getColumn(index + 1);
      column.width = Math.max(15, header.length * 2);
    });

    // 生成二进制数据
    const buffer = await workbook.xlsx.writeBuffer();

    // 创建Blob对象
    const blob = new Blob([buffer], {
      type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    });

    // 创建下载链接并触发下载
    const link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    const pageRangeText =
      exportFormData.startPage && exportFormData.endPage
        ? `_第${exportFormData.startPage}-${exportFormData.endPage}页`
        : "";
    link.download = `用户数据${pageRangeText}(${exportData.length}条).xlsx`;
    link.click();

    ElMessage.success(`成功导出 ${exportData.length} 条数据`);
    exportDialogVisible.value = false;
  } catch (error) {
    console.error("导出失败:", error);
    ElMessage.error("导出失败");
  }
};

// 拆分模板确认逻辑
const handleTemplateConfirm = async () => {
  try {
    if (selectedFields.value.length === 0) {
      ElMessage.warning("请至少选择一个字段");
      return;
    }

    // 获取选中的字段信息，并过滤掉 ID 字段和 must 为 "排除" 的字段
    const selectedFieldsInfo = exportFields.value.filter(
      field =>
        selectedFields.value.includes(field.field) &&
        field.field !== "id" &&
        field.must !== "排除"
    );

    // 如果过滤后没有字段，提示用户
    if (selectedFieldsInfo.length === 0) {
      ElMessage.warning("请至少选择一个有效字段");
      return;
    }

    // 创建工作簿和工作表
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet("用户数据模板");

    // 设置表头
    const headers = selectedFieldsInfo.map(field => {
      // 如果字段是必填的，添加星号标记
      return field.must === "必须" ? `${field.label}*` : field.label;
    });
    worksheet.addRow(headers);

    // 设置表头样式
    const headerRow = worksheet.getRow(1);
    headerRow.font = { bold: true };
    headerRow.alignment = { vertical: "middle", horizontal: "center" };

    // 设置所有行的高度为统一值
    for (let i = 1; i <= 1000; i++) {
      const row = worksheet.getRow(i);
      row.height = 20; // 统一设置所有行高为20
    }

    // 设置列宽和样式
    headers.forEach((header, index) => {
      const column = worksheet.getColumn(index + 1);
      column.width = Math.max(15, header.length * 2);

      // 获取当前字段的配置
      const field = selectedFieldsInfo[index];

      // 设置整列为文本格式
      column.numFmt = "@";

      // 为所有单元格设置文本格式（除了特殊计算字段）
      for (let i = 2; i <= 1000; i++) {
        const cell = worksheet.getCell(`${column.letter}${i}`);
        // 设置单元格格式为文本
        cell.numFmt = "@";
        // 不再添加前导单引号和默认值，让单元格保持空白状态
        cell.value = null;
      }

      // 如果是入学年份字段，添加年份格式验证
      if (field.field === "enrollment_year") {
        for (let i = 2; i <= 1000; i++) {
          const cell = worksheet.getCell(`${column.letter}${i}`);
          cell.dataValidation = {
            type: "custom",
            formulae: ["=AND(ISNUMBER(VALUE(A1)),LEN(A1)=4)"],
            showErrorMessage: true,
            errorStyle: "error",
            errorTitle: "错误",
            error: "请输入正确的年份格式 (YYYY)",
            prompt: "请输入年份 (YYYY)"
          };
          // 保持文本格式
          cell.numFmt = "@";
        }
      }

      // 只有身份状态有效期这样的计算字段才使用日期格式
      if (field.field === "identity_expiry") {
        const studyDurationCol = selectedFieldsInfo.findIndex(
          f => f.field === "study_duration"
        );
        const enrollmentYearCol = selectedFieldsInfo.findIndex(
          f => f.field === "enrollment_year"
        );

        if (studyDurationCol !== -1 && enrollmentYearCol !== -1) {
          const studyDurationLetter = worksheet.getColumn(
            studyDurationCol + 1
          ).letter;
          const enrollmentYearLetter = worksheet.getColumn(
            enrollmentYearCol + 1
          ).letter;

          for (let i = 2; i <= 1000; i++) {
            const cell = worksheet.getCell(`${column.letter}${i}`);
            // 设置计算公式：入学年份加上学制年数，日期固定为6月30日
            cell.value = {
              formula: `=IF(AND(NOT(ISBLANK(${enrollmentYearLetter}${i})),NOT(ISBLANK(${studyDurationLetter}${i}))),DATE(${enrollmentYearLetter}${i}+${studyDurationLetter}${i},6,30),"")`
            };
            // 设置日期格式
            cell.numFmt = "yyyy-mm-dd";
            // 设置背景色为灰色表示是计算字段
            cell.fill = {
              type: "pattern",
              pattern: "solid",
              fgColor: { argb: "FFE0E0E0" }
            };
          }
        }
      }

      // 为必填列添加背景色和边框
      if (field.must === "必须") {
        for (let i = 2; i <= 1000; i++) {
          const cell = worksheet.getCell(`${column.letter}${i}`);
          // 设置背景色
          cell.fill = {
            type: "pattern",
            pattern: "solid",
            fgColor: { argb: "FFFFE0" } // 浅黄色背景
          };
          // 设置边框
          cell.border = {
            top: { style: "thin", color: { argb: "FFD3D3D3" } },
            left: { style: "thin", color: { argb: "FFD3D3D3" } },
            bottom: { style: "thin", color: { argb: "FFD3D3D3" } },
            right: { style: "thin", color: { argb: "FFD3D3D3" } }
          };
        }
      }

      // 如果是枚举类型字段，添加下拉选择
      if (field.type.startsWith("enum(")) {
        try {
          const enumStr = field.type.substring(5, field.type.length - 1);
          const options = enumStr
            .split(",")
            .map(option => option.replace(/['"]/g, "").trim());

          for (let i = 2; i <= 1000; i++) {
            const cell = worksheet.getCell(`${column.letter}${i}`);
            cell.dataValidation = {
              type: "list",
              allowBlank: field.must !== "必须",
              formulae: ['"' + options.join(",") + '"'],
              showErrorMessage: true,
              errorStyle: "warning",
              errorTitle: "提示",
              error: `请从下拉列表中选择有效的${field.label}`,
              prompt: `请选择${field.label}`
            };
          }
        } catch (e) {
          console.error("解析枚举值失败:", e);
        }
      }
    });

    // 冻结表头
    worksheet.views = [
      {
        state: "frozen",
        xSplit: 0,
        ySplit: 1,
        topLeftCell: "A2",
        activeCell: "A2"
      }
    ];

    // 隐藏验证工作表
    const validationSheet = workbook.getWorksheet("Validation");
    if (validationSheet) {
      validationSheet.state = "hidden";
    }

    // 生成二进制数据
    const buffer = await workbook.xlsx.writeBuffer();

    // 创建Blob对象
    const blob = new Blob([buffer], {
      type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    });

    // 创建下载链接并触发下载
    const link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    // 获取当前表的描述作为文件名的一部分
    const currentTable = availableTables.value.find(
      t => t.name === activeTable.value
    );
    const tableName = currentTable?.description || "用户数据";
    link.download = `${tableName}导入模板.xlsx`;
    link.click();

    ElMessage.success("模板下载成功");
    exportDialogVisible.value = false;
  } catch (error) {
    console.error("下载模板失败:", error);
    ElMessage.error("下载模板失败");
  }
};

// 全选字段
const selectAllFields = () => {
  selectedFields.value = exportFields.value.map(field => field.field);
};

// 取消全选
const unselectAllFields = () => {
  selectedFields.value = [];
};

// 计算选中的预览字段
const selectedPreviewFields = computed(() => {
  return exportFields.value.filter(field =>
    selectedFields.value.includes(field.field)
  );
});

// 计算导出条数提示文字
const getExportCountText = computed(() => {
  if (exportFormData.startPage && exportFormData.endPage) {
    const pageSize = pagination.pageSize;
    const totalPages = Math.ceil(pagination.total / pageSize);
    const validStartPage = Math.min(exportFormData.startPage, totalPages);
    const validEndPage = Math.min(exportFormData.endPage, totalPages);
    const count = (validEndPage - validStartPage + 1) * pageSize;
    return `将导出约 ${Math.min(count, 1000)} 条数据（页码范围内）`;
  }
  return "最多导出1000条数据";
});

// 处理页码范围变化
const handlePageRangeChange = () => {
  if (exportFormData.startPage && exportFormData.endPage) {
    if (exportFormData.startPage > exportFormData.endPage) {
      ElMessage.warning("起始页码不能大于结束页码");
      return;
    }
    const pageSize = pagination.pageSize;
    const totalPages = Math.ceil(pagination.total / pageSize);
    const validStartPage = Math.min(exportFormData.startPage, totalPages);
    const validEndPage = Math.min(exportFormData.endPage, totalPages);
    const count = (validEndPage - validStartPage + 1) * pageSize;
    exportFormData.count = Math.min(count, 1000);
  }
};

// 修改编辑按钮的显示逻辑
const canEdit = (row: any) => {
  // 检查是否有任何字段的修改权限
  return fields.value.some(
    field =>
      !["id", "created_at", "updated_at"].includes(field.field) &&
      hasFieldSetPermission(field.field)
  );
};

// 在 script 部分添加相关变量和方法
const isExportQueryCollapse = ref(true);
const exportQueryForm = reactive({});
const exportQueryResult = ref([]);

// 切换导出查询条件的折叠状态
const toggleExportQueryCollapse = () => {
  isExportQueryCollapse.value = !isExportQueryCollapse.value;
};

// 处理导出查询
const handleExportQuery = async () => {
  try {
    // 构建查询参数
    const params = {
      ...exportQueryForm,
      page: 1,
      size: 1000, // 最大导出数量
      table_id: tableId.value
    };

    const res = await exportUser(params);
    if (res.status === "success") {
      exportQueryResult.value = res.data.data.records;
      // 更新导出数量
      exportFormData.count = Math.min(exportQueryResult.value.length, 1000);
      ElMessage.success(`查询到 ${exportQueryResult.value.length} 条数据`);
    }
  } catch (error) {
    console.error("查询失败:", error);
    ElMessage.error("查询失败");
  }
};

// 重置导出查询表单
const resetExportQuery = () => {
  Object.keys(exportQueryForm).forEach(key => {
    exportQueryForm[key] = "";
  });
  exportQueryResult.value = [];
  exportFormData.count = 100;
};

// 处理表格切换
const handleTableChange = async () => {
  loading.value = true;
  try {
    // 重置分页
    pagination.currentPage = 1;

    // 清空编辑弹出框内容
    dialogVisible.value = false;
    dialogTitle.value = "";
    Object.keys(formData).forEach(key => {
      formData[key] = "";
    });
    currentRow.value = null;

    // 清空编辑记录
    editedFields.value.clear();

    // 清空单元格编辑状态
    editingCell.value = {
      rowId: null,
      prop: null
    };
    editingValue.value = "";
    isConfirming.value = false;

    // 重置查询表单 - 确保完全清空所有字段
    Object.keys(queryForm).forEach(key => {
      delete queryForm[key];
    });

    // 获取新表的数据
    await fetchData();

    // 等待字段加载完成后，重新初始化查询表单
    await nextTick();
    fields.value.forEach(field => {
      queryForm[field.field] = "";
    });

    // 加载新表的搜索历史
    loadSearchHistory();
  } catch (error) {
    console.error("切换表格失败:", error);
    ElMessage.error("切换表格失败");
  } finally {
    loading.value = false;
  }
};

// 添加判断列是否可见的方法
const isColumnVisible = column => {
  const field = fields.value.find(f => f.field === column.property);
  if (!field) return true;
  try {
    const config = JSON.parse(field.config || "{}");
    return config.visible !== false;
  } catch (e) {
    return true;
  }
};

// 添加查看隐藏内容的处理方法
const handleViewHiddenContent = async (row, column) => {
  const field = fields.value.find(f => f.field === column.property);
  if (!field) return;

  try {
    // 调用getTableRecords接口获取数据
    const res = await getTableRecords({
      field_id: field.field_id,
      record_id: row.id
    });

    if (res.status === "success") {
      // 构建显示信息，包含ID和姓名
      const userInfo = `<div style="line-height: 2;">姓名：${row.name}<br>证件号：${res.data || "-"}</div>`;

      // 显示获取到的数据
      ElMessageBox.alert(userInfo, field.label, {
        dangerouslyUseHTMLString: true,
        confirmButtonText: "确定",
        callback: () => {}
      });
    } else {
      ElMessage.error(res.message || "获取数据失败");
    }
  } catch (error) {
    console.error("获取数据失败:", error);
    ElMessage.error("获取数据失败");
  }
};

// 添加导入相关的方法
const handleImportExcel = async (file: File) => {
  try {
    // 获取表字段信息用于映射
    const fieldsRes = await getAllTableField({ table_id: tableId.value });
    if (fieldsRes.status !== "success") {
      throw new Error(fieldsRes.message || "获取字段信息失败");
    }

    // 创建 label 到 field 的映射
    const labelToFieldMap = {};
    const fieldConfigs = {};
    fieldsRes.data.forEach(field => {
      // 去掉必填标记*
      const cleanLabel = field.label.replace("*", "");
      labelToFieldMap[cleanLabel] = field.field;
      fieldConfigs[field.field] = field;
    });

    // 读取Excel文件
    const workbook = new ExcelJS.Workbook();
    await workbook.xlsx.load(await file.arrayBuffer());

    // 获取第一个工作表
    const worksheet = workbook.worksheets[0];
    if (!worksheet) {
      throw new Error("Excel文件为空");
    }

    // 获取表头（第一行）
    const headers = [];
    const headerConfigs = {}; // 存储表头配置，包括是否必填
    worksheet.getRow(1).eachCell((cell, colNumber) => {
      const headerText = cell.value?.toString() || "";
      // 检查是否有*标记
      const isRequired = headerText.includes("*");
      // 去掉*标记用于字段匹配
      const cleanHeader = headerText.replace("*", "");
      headers[colNumber - 1] = cleanHeader;
      headerConfigs[colNumber - 1] = {
        original: headerText,
        isRequired,
        clean: cleanHeader
      };
    });

    // 验证必填字段是否都存在
    const missingRequiredFields = fieldsRes.data
      .filter(field => field.must === "必须")
      .filter(field => !headers.includes(field.label.replace("*", "")));

    if (missingRequiredFields.length > 0) {
      throw new Error(
        `缺少必填字段：${missingRequiredFields.map(f => f.label).join(", ")}`
      );
    }

    // 读取数据并转换
    const data = [];
    const errors = [];

    worksheet.eachRow((row, rowNumber) => {
      // 跳过表头行
      if (rowNumber === 1) return;

      const rowData = {};
      const rowErrors = [];
      const filledColumns = new Set<number>(); // 记录已填写数据的列号

      // 首先检查哪些列有数据
      row.eachCell((cell, colNumber) => {
        const cellValue = cell.value;
        // 检查单元格是否有有效值（排除空值、空字符串、公式等）
        if (
          cellValue !== null &&
          cellValue !== undefined &&
          !(typeof cellValue === "string" && cellValue.trim() === "") &&
          !(
            typeof cellValue === "object" &&
            (!cellValue || Object.keys(cellValue).length === 0)
          ) &&
          !(
            cell.formula ||
            (typeof cellValue === "string" && cellValue.startsWith("="))
          )
        ) {
          filledColumns.add(colNumber);
        }
      });

      // 只有当行中有数据时才进行校验
      if (filledColumns.size > 0) {
        // 检查所有必填字段
        headers.forEach((header, colIndex) => {
          const field = labelToFieldMap[header];
          if (field && fieldConfigs[field].must === "必须") {
            const cell = row.getCell(colIndex + 1);
            const cellValue = cell.value;

            // 跳过计算公式字段
            if (
              cell.formula ||
              (typeof cellValue === "string" && cellValue.startsWith("="))
            ) {
              return;
            }

            // 检查单元格值是否为空
            const isEmpty =
              cellValue === null ||
              cellValue === undefined ||
              (typeof cellValue === "string" && cellValue.trim() === "") ||
              (typeof cellValue === "object" &&
                (!cellValue || Object.keys(cellValue).length === 0));

            if (isEmpty) {
              rowErrors.push(`${fieldConfigs[field].label}不能为空`);
            }
          }
        });
      }

      // 处理每个单元格的数据
      row.eachCell((cell, colNumber) => {
        const label = headers[colNumber - 1];
        const field = labelToFieldMap[label];

        if (field) {
          // 移除filledColumns.has(colNumber)检查，处理所有字段
          const fieldConfig = fieldConfigs[field];
          // 检查单元格的值
          const cellValue = cell.value;

          // 跳过计算字段
          if (
            cell.formula ||
            (typeof cellValue === "string" && cellValue.startsWith("="))
          ) {
            return;
          }

          // 处理不同类型的单元格值
          let finalValue = "";

          if (cellValue) {
            // 处理富文本
            if (typeof cellValue === "object" && "richText" in cellValue) {
              finalValue = (
                cellValue as { richText: Array<{ text: string }> }
              ).richText
                .map(rt => rt.text)
                .join("");
            }
            // 处理普通文本
            else if (typeof cellValue === "string") {
              finalValue = cellValue.startsWith("'")
                ? cellValue.substring(1)
                : cellValue;
            }
            // 处理其他类型
            else {
              finalValue = cellValue.toString();
            }

            // 只在有值的情况下进行其他验证
            if (finalValue.trim() !== "") {
              // 枚举字段验证
              if (fieldConfig.type.startsWith("enum(")) {
                const enumStr = fieldConfig.type.substring(
                  5,
                  fieldConfig.type.length - 1
                );
                const options = enumStr
                  .split(",")
                  .map(option => option.replace(/['"]/g, "").trim());

                if (!options.includes(finalValue)) {
                  rowErrors.push(
                    `${fieldConfig.label}的值必须是: ${options.join(", ")} 之一`
                  );
                }
              }

              // 年份格式验证
              if (field === "enrollment_year" && finalValue) {
                const yearPattern = /^\d{4}$/;
                if (!yearPattern.test(finalValue)) {
                  rowErrors.push(`${fieldConfig.label}必须是4位数字的年份格式`);
                }
              }

              rowData[field] = finalValue;
            }
          }
        }
      });

      if (rowErrors.length > 0) {
        errors.push({
          row: rowNumber,
          errors: rowErrors
        });
      }

      if (Object.keys(rowData).length > 0) {
        data.push(rowData);
      }
    });

    // 如果有错误，显示错误信息并终止导入
    if (errors.length > 0) {
      const errorMessage = errors
        .map(error => `第${error.row}行: ${error.errors.join("; ")}`)
        .join("\n");

      // 使用 ElMessageBox 显示格式化的错误信息
      await ElMessageBox.alert(errorMessage, "数据验证错误", {
        type: "error",
        dangerouslyUseHTMLString: true,
        confirmButtonText: "确定",
        customClass: "import-error-dialog",
        center: false,
        showClose: true,
        closeOnClickModal: false,
        customStyle: {
          width: "1200px",
          maxWidth: "90vw"
        }
      });
      return;
    }

    // 调用导入接口
    const importRes = await importField({
      table_id: tableId.value,
      data
    });

    if (importRes.status === "success") {
      ElMessage.success("导入成功");
      fetchData(); // 刷新数据
    } else {
      ElMessage.error(importRes.message || "导入失败");
    }
  } catch (error) {
    console.error("导入失败:", error);
    ElMessage.error(error.message || "导入失败");
  }
};

// 添加选择相关的变量
const selectedRows = ref<any[]>([]);

const handleSelectionChange = (selection: any[]) => {
  if (selection.length > 30) {
    // 如果选择超过30个，则只保留前30个
    const table = document.querySelector(".el-table");
    if (table) {
      // @ts-ignore
      table.__vue__?.clearSelection();
      selection.slice(0, 30).forEach(row => {
        // @ts-ignore
        table.__vue__?.toggleRowSelection(row, true);
      });
    }
    ElMessage.warning("最多只能选择30个用户");
    return;
  }
  selectedRows.value = selection;
};

// 添加生成授权码相关的变量
const authCodeDialogVisible = ref(false);
const isAuthCodeMode = ref(false);
const authCodePagination = reactive({
  pageSize: 10,
  currentPage: 1,
  pageSizes: [10, 15, 20],
  total: 0,
  align: "right",
  background: true,
  size: "default"
});

// 为单个用户生成授权码
const handleGenerateAuthCodeForUser = (user: any) => {
  selectedRows.value = [user];
  handleGenerateAuthCode();
};

// 添加授权码导出相关的变量
const authCodeExportDialogVisible = ref(false);
const authCodeExportFields = ref<Field[]>([]);
const selectedAuthCodeFields = ref<string[]>([]);
const authCodeExportData = ref<any[]>([]);

// 修改生成授权码的处理方法
const handleGenerateAuthCode = async () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning("请选择需要生成授权码的用户");
    return;
  }

  if (selectedRows.value.length > 30) {
    ElMessage.warning("最多只能选择30个用户");
    return;
  }

  try {
    // 构建请求数据
    const requestData = {
      table_id: tableId.value,
      data: selectedRows.value.map(user => ({
        henau_number: user.henau_number || ""
      }))
    };

    // 调用生成授权码的API
    const res = await generateCertificateNumber(requestData);

    if (res.status === "success") {
      ElMessage.success(`已为 ${selectedRows.value.length} 个用户生成授权码`);

      // 保存返回的数据用于导出
      authCodeExportData.value = res.data;

      // 准备导出字段，使用API返回的字段信息
      const availableFields: Field[] = Object.keys(res.data[0] || {}).map(
        field => {
          const fieldInfo = fields.value.find(f => f.field === field);
          return {
            field_id: fieldInfo?.field_id || 0,
            field,
            label: fieldInfo?.label || field,
            type: "str"
          };
        }
      );

      authCodeExportFields.value = availableFields;
      selectedAuthCodeFields.value = [
        "henau_number",
        "authorization_number",
        "name",
        "class_name"
      ];

      // 显示导出配置对话框
      authCodeExportDialogVisible.value = true;
    } else {
      ElMessage.error(res.message || "生成授权码失败");
    }
  } catch (error) {
    console.error("生成授权码失败:", error);
    ElMessage.error("生成授权码失败");
  }
};

// 修改导出授权码Excel的方法
const handleAuthCodeExport = async () => {
  try {
    if (selectedAuthCodeFields.value.length === 0) {
      ElMessage.warning("请至少选择一个导出字段");
      return;
    }

    // 创建Excel文件并下载
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet("授权码");

    // 设置表头（使用中文标签）
    const headers = selectedAuthCodeFields.value.map(field => {
      const fieldInfo = fields.value.find(f => f.field === field);
      return fieldInfo ? fieldInfo.label : field;
    });
    worksheet.addRow(headers);

    // 添加数据
    authCodeExportData.value.forEach(item => {
      const rowData = selectedAuthCodeFields.value.map(
        field => item[field] || ""
      );
      worksheet.addRow(rowData);
    });

    // 设置列宽
    headers.forEach((_, index) => {
      worksheet.getColumn(index + 1).width = 20;
    });

    // 设置表头样式
    const headerRow = worksheet.getRow(1);
    headerRow.font = { bold: true };
    headerRow.alignment = { vertical: "middle", horizontal: "center" };

    // 设置所有行的高度为统一值
    for (let i = 1; i <= 1000; i++) {
      const row = worksheet.getRow(i);
      row.height = 20; // 统一设置所有行高为20
    }

    // 生成二进制数据
    const buffer = await workbook.xlsx.writeBuffer();

    // 创建Blob对象
    const blob = new Blob([buffer], {
      type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
    });

    // 创建下载链接并触发下载
    const link = document.createElement("a");
    link.href = window.URL.createObjectURL(blob);
    link.download = `授权码_${new Date().toLocaleDateString()}.xlsx`;
    link.click();

    // 关闭对话框
    authCodeExportDialogVisible.value = false;
    // 清空数据
    selectedRows.value = [];
    fetchData(); // 刷新数据
  } catch (error) {
    console.error("导出Excel失败:", error);
    ElMessage.error("导出Excel失败");
  }
};

// 添加全选/取消全选方法
const selectAllAuthCodeFields = () => {
  selectedAuthCodeFields.value = authCodeExportFields.value.map(
    field => field.field
  );
};

const unselectAllAuthCodeFields = () => {
  selectedAuthCodeFields.value = [];
};

// 修改授权码预览数据的计算属性
const authCodePreviewData = computed(() => {
  if (authCodeExportData.value.length === 0) return [];

  // 创建一个新的对象用于预览
  const previewItem = {};

  // 遍历选中的字段，使用中文标签作为键名
  selectedAuthCodeFields.value.forEach(field => {
    const fieldInfo = fields.value.find(f => f.field === field);
    if (fieldInfo) {
      // 使用字段名作为键，这样表格可以正确显示数据
      previewItem[field] = authCodeExportData.value[0][field] || "";
    }
  });

  return [previewItem];
});

// 修改用于显示的字段列表计算属性
const previewFields = computed(() => {
  return selectedAuthCodeFields.value.map(field => {
    const fieldInfo = fields.value.find(f => f.field === field);
    return {
      field,
      label: fieldInfo ? fieldInfo.label : field,
      field_id: fieldInfo?.field_id || 0
    };
  });
});

// 恢复预览数据的定义
const previewData = computed(() => {
  if (exportQueryResult.value.length === 0) return [];
  return [exportQueryResult.value[0]]; // 只显示第一条数据作为预览
});

// 添加压缩文件上传相关的处理函数
const handleBeforeUploadArchive = (file: File) => {
  const validExtensions = [".zip", ".rar", ".7z"];
  const extension = file.name
    .substring(file.name.lastIndexOf("."))
    .toLowerCase();

  if (!validExtensions.includes(extension)) {
    ElMessage.error("只能上传 ZIP、RAR 或 7Z 格式的压缩文件！");
    return false;
  }

  const maxSize = 100; // 最大文件大小（MB）
  const fileSize = file.size / 1024 / 1024;

  if (fileSize > maxSize) {
    ElMessage.error(`文件大小不能超过 ${maxSize}MB！`);
    return false;
  }

  return true;
};

const handleUploadArchive = async (file: File) => {
  if (!file) return;

  try {
    loading.value = true;
    // 创建FormData对象，只包含文件
    const formData = new FormData();
    formData.append("file", file);

    const res = await uploadFile({
      formData,
      params: {
        table_id: tableId.value
      }
    });

    if (res.status === "success") {
      ElMessage.success("压缩包上传成功");
    } else {
      ElMessage.error(res.msg || "上传失败");
    }
  } catch (error) {
    console.error("文件上传失败:", error);
    ElMessage.error("文件上传失败");
  } finally {
    loading.value = false;
  }
};

// 添加枚举类型相关的工具函数
const isEnumField = (fieldName: string) => {
  const field = fields.value.find(f => f.field === fieldName);
  return field?.type.startsWith("enum(");
};

const getEnumOptions = (fieldName: string) => {
  const field = fields.value.find(f => f.field === fieldName);
  if (!field || !field.type.startsWith("enum(")) return [];

  try {
    // 从类型字符串中提取枚举值
    const enumStr = field.type.substring(5, field.type.length - 1);
    // 解析枚举值字符串为数组
    return JSON.parse(`[${enumStr}]`);
  } catch (e) {
    console.error("解析枚举值失败:", e);
    return [];
  }
};

onMounted(async () => {
  await fetchAvailableTables(); // 先获取可用的表
  await fetchPermissions(); // 再获取权限
  await fetchData(); // 最后获取数据
  loadSearchHistory(); // 加载搜索历史
});

// 添加导入权限检查的计算属性
const hasImportPermission = computed(() => {
  return permissions.value.includes(`table.${tableField.value}.import`);
});

// 添加记录编辑过的字段状态
const editedFields = ref(new Map<number, Set<string>>()); // key: rowId, value: Set of edited field names

// 添加判断字段是否被编辑过的方法
const isFieldEdited = (row: any, field: string) => {
  return editedFields.value.get(row.id)?.has(field) || false;
};

// 在 script 部分添加权限检查的计算属性
// ... existing code ...
// 添加删除权限检查的计算属性
const hasDeletePermission = computed(() => {
  return permissions.value.includes(`table.${tableField.value}.delete`);
});

// 添加上传图片权限检查的计算属性
const hasUploadImagePermission = computed(() => {
  return permissions.value.includes(`table.${tableField.value}.uploadImage`);
});

// ... existing code ...

// 添加导出权限检查的计算属性
const hasExportPermission = computed(() => {
  return permissions.value.includes(`table.${tableField.value}.export`);
});

// 添加生成授权码权限检查的计算属性
const hasGenerateAuthCodePermission = computed(() => {
  return permissions.value.includes(`table.${tableField.value}.generate`);
});

// ... existing code ...

// 添加计算属性用于过滤photo列
const photoColumns = computed(() => {
  return columns.value.filter(col => col.prop?.endsWith("_photo"));
});

// ... existing code ...

// 添加搜索历史相关的响应式变量
const searchHistory = ref<Array<Record<string, any>>>([]);
const MAX_HISTORY_LENGTH = 10;

// 从localStorage加载搜索历史
const loadSearchHistory = () => {
  try {
    const savedHistory = localStorage.getItem(
      `search_history_${tableId.value}`
    );
    if (savedHistory) {
      searchHistory.value = JSON.parse(savedHistory);
    }
  } catch (error) {
    console.error("加载搜索历史失败:", error);
  }
};

// 保存搜索历史到localStorage
const saveSearchHistory = () => {
  try {
    localStorage.setItem(
      `search_history_${tableId.value}`,
      JSON.stringify(searchHistory.value)
    );
  } catch (error) {
    console.error("保存搜索历史失败:", error);
  }
};

// 应用历史搜索条件
const applySearchHistory = (history: Record<string, any>) => {
  // 重置查询表单
  Object.keys(queryForm).forEach(key => {
    queryForm[key] = "";
  });

  // 应用历史记录中的查询条件
  Object.entries(history).forEach(([key, value]) => {
    if (key in queryForm) {
      queryForm[key] = value;
    }
  });

  // 执行查询
  handleQuery();
};

// 移除单个搜索历史
const removeSearchHistory = (index: number) => {
  searchHistory.value.splice(index, 1);
  saveSearchHistory();
};

// 清空搜索历史
const clearSearchHistory = async () => {
  try {
    await ElMessageBox.confirm("确定要清空所有搜索历史记录吗？", "提示", {
      confirmButtonText: "确定",
      cancelButtonText: "取消",
      type: "warning"
    });
    searchHistory.value = [];
    saveSearchHistory();
  } catch (error) {
    // 用户取消操作
  }
};

// 获取历史记录的显示标签
const getHistoryLabel = (history: Record<string, any>) => {
  const labels = Object.entries(history)
    .map(([key, value]) => {
      const field = fields.value.find(f => f.field === key);
      if (field) {
        return `${field.label}: ${value}`;
      }
      return null;
    })
    .filter(Boolean);

  // 如果标签太长，只显示前两个条件
  if (labels.length > 2) {
    return `${labels.slice(0, 2).join(", ")}...`;
  }
  return labels.join(", ");
};

// 获取历史记录的完整提示
const getHistoryTooltip = (history: Record<string, any>) => {
  return Object.entries(history)
    .map(([key, value]) => {
      const field = fields.value.find(f => f.field === key);
      if (field) {
        return `${field.label}: ${value}`;
      }
      return null;
    })
    .filter(Boolean)
    .join("\n");
};

// ... other existing code ...

// 添加搜索历史弹出框的变量
const searchHistoryDialogVisible = ref(false);

// 添加格式化时间的函数
const formatTime = (timestamp: number) => {
  return new Date(timestamp).toLocaleString();
};

// 添加显示搜索历史弹出框的方法
const showSearchHistoryDialog = () => {
  searchHistoryDialogVisible.value = true;
};
</script>

<style lang="scss" scoped>
.adminer-container {
  height: 100%;
  padding: 5px;

  :deep(.el-card) {
    display: flex;
    flex-direction: column;
    height: 84vh;

    .el-card__header {
      flex-shrink: 0;
      padding: 4px 15px;
    }

    .el-card__body {
      flex: 1;
      padding: 4px 15px;
      overflow: auto;
    }
  }

  .card-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-top: 3px;
    margin-bottom: 4px;

    .ml-auto {
      margin-left: auto;
    }
  }

  :deep(.el-table) {
    margin-top: 10px;
  }

  .mb-4 {
    margin-bottom: 0.8rem;
  }

  .mr-1 {
    margin-right: 0.25rem;
  }

  .mr-2 {
    margin-right: 0.5rem;
  }

  // 导入导出按钮样式
  .flex-center {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    padding: 0 16px;
    font-size: 14px;
    border-radius: 4px;
    transition: all 0.3s;

    &:hover {
      box-shadow: 0 2px 8px rgb(0 0 0 / 10%);
      transform: translateY(-1px);
    }

    .el-icon {
      font-size: 16px;
    }
  }

  // 折叠动画相关样式
  :deep(.el-collapse-transition) {
    transition: all 0.3s ease-in-out;

    .flex {
      width: 100%;
      margin-top: 8px;
      transition: all 0.3s ease-in-out;
    }
  }

  // 优化展开后的查询表单样式
  :deep(.el-form) {
    .el-form-item {
      display: flex;
      align-items: center;
      margin-bottom: 12px;

      &__label {
        width: 140px !important;
        padding-right: 12px;
        font-size: 14px;
        line-height: 32px;
        color: var(--el-text-color-regular);
        text-align: right;
        white-space: nowrap;
      }

      &__content {
        .el-input {
          .el-input__wrapper {
            height: 36px;
            padding: 0 12px;
            box-shadow: 0 0 0 1px var(--el-border-color);
            transition: all 0.3s;

            &:hover {
              box-shadow: 0 0 0 1px var(--el-border-color-hover);
            }

            &.is-focus {
              box-shadow: 0 0 0 1px var(--el-color-primary) !important;
            }
          }
        }
      }
    }
  }

  // 优化按钮组样式
  :deep(.el-button) {
    height: 36px;
    padding: 8px 16px;
    font-size: 14px;

    .el-icon {
      font-size: 16px;
    }
  }

  // 优化间距
  .gap-4 {
    gap: 16px;
  }

  .mt-4 {
    margin-top: 16px;
  }
}

:deep(.el-table) {
  // 表格基础样式
  .cell {
    padding: 2px 4px;
    line-height: 1;
  }

  // 表头样式
  .el-table__header {
    th {
      height: 36px;
      padding: 2px 4px;
      font-weight: bold;
      color: var(--el-text-color-primary);
      background-color: var(--el-fill-color-light);
    }
  }

  .el-table__row {
    height: 36px;
    cursor: pointer;
    transition: all 0.3s ease-in-out;

    &:hover {
      background-color: var(--el-fill-color-lighter);
    }
  }

  // 编辑相关样式
  .el-input {
    margin: -2px;

    .el-input__inner {
      height: 70%;
      padding: 2px 4px;
      border: none;

      &:focus {
        box-shadow: 0 0 0 2px var(--el-color-primary-light-3);
      }
    }
  }
}

.field-selection {
  width: 100%;
  padding: 20px;
  background-color: var(--el-fill-color-blank);
  border: 1px solid var(--el-border-color);
  border-radius: 4px;

  :deep(.el-checkbox) {
    width: 100%;
    height: 32px;
    margin-right: 0;
    margin-bottom: 12px;

    .el-checkbox__label {
      overflow: hidden;
      line-height: 32px;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
}

.preview-table {
  :deep(.el-table) {
    // 设置表头样式
    th {
      height: 40px;
      font-size: 13px;
      font-weight: bold;
      color: var(--el-text-color-primary);
      background-color: var(--el-fill-color-light);
    }

    // 设置单元格样式
    td {
      height: 36px;
      font-size: 13px;
      color: var(--el-text-color-regular);
    }

    // 鼠标悬停效果
    .el-table__row:hover {
      td {
        background-color: var(--el-fill-color-lighter);
      }
    }
  }
}

// 添加禁用列的样式
:deep(.disabled-column) {
  .cell {
    color: var(--el-text-color-disabled);
    cursor: not-allowed;
  }
}

// 添加禁用输入框的样式
:deep(.is-disabled) {
  .el-input__inner {
    color: var(--el-text-color-disabled);
    cursor: not-allowed;
    background-color: var(--el-fill-color-light);
  }
}

// 优化查询条件样式
:deep(.query-conditions) {
  .label-container {
    font-size: 14px;
    color: var(--el-text-color-regular);
    text-align: left;

    .truncate {
      display: inline-block;
      max-width: 100%;
    }
  }

  .el-input {
    .el-input__wrapper {
      width: 100%;
    }
  }
}

// 添加编辑对话框的样式
:deep(.edit-dialog) {
  :deep(.el-dialog__body) {
    padding: 20px;
  }

  .edit-form {
    :deep(.el-form-item) {
      margin-bottom: 16px;

      &:last-child {
        margin-bottom: 0;
      }

      .el-form-item__content {
        width: 100%;

        .el-select,
        .el-input {
          width: 100%;
        }
      }
    }
  }
}

:deep(.import-error-dialog) {
  width: 1200px !important;
  min-width: 1200px !important;
  max-width: 90vw !important;

  .el-message-box {
    width: 1200px !important;
    max-width: 90vw !important;
  }

  .el-message-box__content {
    max-height: 60vh;
    padding: 20px;
    overflow-y: auto;
    font-size: 14px;
    line-height: 1.8;
    white-space: pre-line;
  }

  .el-message-box__container {
    word-break: break-all;
  }

  .el-message-box__header {
    padding: 15px 20px;
  }
}

.query-form-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  align-items: flex-start;
}

.query-form-item {
  display: flex;
  align-items: center;
  margin: 0;

  :deep(.el-form-item__label) {
    width: auto;
    min-width: 70px;
    padding-right: 8px;
    font-size: 14px;
    line-height: 32px;
    white-space: nowrap;
  }

  :deep(.el-form-item__content) {
    margin-left: 0 !important;
  }

  :deep(.el-input),
  :deep(.el-select) {
    width: 180px;
  }
}

// 添加编辑确认对话框样式
:deep(.edit-confirm-dialog) {
  .el-message-box__content {
    .change-title {
      margin-bottom: 12px;
      font-size: 16px;
      font-weight: bold;
      color: var(--el-text-color-primary);
    }

    .change-message {
      padding: 12px;
      margin-bottom: 8px;
      background-color: var(--el-fill-color-lighter);
      border-radius: 4px;

      .change-header {
        padding-bottom: 8px;
        margin-bottom: 8px;
        border-bottom: 1px solid var(--el-border-color-lighter);

        .user-name {
          font-weight: bold;
          color: var(--el-color-primary);
        }
      }

      .change-content {
        display: flex;
        gap: 12px;
        align-items: center;

        .field-name {
          min-width: 80px;
          font-weight: bold;
          color: var(--el-text-color-primary);
        }

        .value-change {
          display: flex;
          flex: 1;
          gap: 8px;
          align-items: center;
          padding: 8px;
          background-color: var(--el-fill-color-blank);
          border-radius: 4px;

          .old-value {
            color: var(--el-text-color-secondary);
          }

          .arrow {
            font-weight: bold;
            color: var(--el-color-primary);
          }

          .new-value {
            font-weight: bold;
            color: var(--el-color-success);
          }
        }
      }
    }
  }
}

// 添加成功消息样式
:deep(.edit-success-notification) {
  min-width: 380px !important;
  padding: 12px !important;

  .success-message {
    .change-message {
      padding: 8px;
      margin-top: 8px;
      background-color: var(--el-fill-color-lighter);
      border-radius: 4px;

      .change-header {
        padding-bottom: 8px;
        margin-bottom: 8px;
        border-bottom: 1px solid var(--el-border-color-lighter);

        .user-name {
          font-weight: bold;
          color: var(--el-color-primary);
        }
      }

      .change-content {
        display: flex;
        gap: 12px;
        align-items: center;

        .field-name {
          min-width: 80px;
          font-weight: bold;
          color: var(--el-text-color-primary);
        }

        .value-change {
          display: flex;
          flex: 1;
          gap: 8px;
          align-items: center;
          padding: 4px;
          font-size: 13px;
          background-color: var(--el-fill-color-blank);
          border-radius: 4px;

          .old-value {
            color: var(--el-text-color-secondary);
          }

          .arrow {
            font-weight: bold;
            color: var(--el-color-primary);
          }

          .new-value {
            font-weight: bold;
            color: var(--el-color-success);
          }
        }
      }
    }
  }
}

// 添加编辑过的单元格高亮样式
:deep(.edited-cell) {
  position: relative;

  &::after {
    position: absolute;
    top: 0;
    right: 0;
    width: 0;
    height: 0;
    content: "";
    border-color: transparent var(--el-color-warning-light-5) transparent
      transparent;
    border-style: solid;
    border-width: 0 8px 8px 0;
  }
}

.operation-buttons-container {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  width: 100%;

  @media (width <= 768px) {
    flex-direction: column;
    align-items: stretch;

    .operation-group {
      justify-content: flex-start;
    }

    .operation-tag {
      flex: 1;
      text-align: center;
    }

    .el-button {
      flex: 1;
    }
  }

  @media (width <= 480px) {
    .operation-group {
      flex-direction: column;
      width: 100%;

      .operation-tag,
      .el-button {
        width: 100%;
      }
    }
  }

  .operation-group {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    align-items: center;
  }
}

.operation-tag {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 100px;
  padding: 8px 16px;
  font-size: 14px;
  white-space: nowrap;
  cursor: pointer;
  border: none;
  transition: all 0.3s ease-in-out;

  &:hover {
    box-shadow: 0 2px 6px rgb(0 0 0 / 10%);
    transform: translateY(-1px);
  }

  .el-icon {
    margin-right: 4px;
    font-size: 14px;
  }
}

.upload-inline {
  display: inline-block;

  :deep(.el-upload) {
    display: block;
  }
}

.search-history-container {
  width: 100%;
  padding: 12px;
  margin-top: 12px;
  background-color: var(--el-fill-color-blank);
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 4px;

  .search-history-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;

    .search-history-title {
      font-size: 14px;
      font-weight: bold;
      color: var(--el-text-color-primary);
    }

    .el-button {
      padding: 0;
      font-size: 14px;
    }
  }

  .search-history-list {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;

    .search-history-item {
      display: inline-flex;
      align-items: center;
      max-width: 300px;
      padding: 6px 10px;
      cursor: pointer;
      transition: all 0.3s ease;

      &:hover {
        background-color: var(--el-color-primary-light-9);
      }

      .search-history-content {
        display: inline-block;
        max-width: 250px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .el-icon {
        margin-left: 4px;
        font-size: 12px;
      }
    }
  }
}

// ... other existing styles ...

.search-history-dialog {
  padding: 20px;

  .search-history-list {
    max-height: 300px;
    overflow-y: auto;

    .search-history-item {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 10px;
      margin-bottom: 10px;
      background-color: var(--el-fill-color-blank);
      border: 1px solid var(--el-border-color-lighter);
      border-radius: 4px;

      .search-history-content {
        flex: 1;
        margin-right: 10px;
      }

      .search-history-time {
        font-size: 12px;
        color: var(--el-text-color-secondary);
      }

      .search-history-actions {
        display: flex;
        gap: 10px;

        .el-button {
          padding: 5px 10px;
          font-size: 12px;
        }
      }
    }
  }

  .search-history-empty {
    margin-top: 10px;
    color: var(--el-text-color-secondary);
    text-align: center;
  }
}

.dialog-footer {
  display: flex;
  justify-content: space-between;
  margin-top: 20px;

  .el-button {
    width: 100px;
  }
}
</style>
